/*
 * marketsim-eclipsetrader
 *
 * Copyright (C) 2008-2011 Steve Phelps and John Cartlidge
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 */
package victria.marketsim.core;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;

import org.apache.log4j.Logger;

public class OrderBook implements Serializable {
	
	/**
	 * The current outstanding bid orders.
	 */
	protected TreeSet<Order> bids;
	
	/**
	 * The current outstanding ask orders.
	 */
	protected TreeSet<Order> asks;

	static Logger logger = Logger.getLogger(OrderBook.class);
	
	public OrderBook() {
		bids = new TreeSet<Order>(new DescendingOrderComparator());
		asks = new TreeSet<Order>(new AscendingOrderComparator());
	}
	
	public Spread getSpread() {
		Spread result = new Spread();
		Order ask = asks.first();
		if ( ask != null) {
			result.setAskPrice(ask.getPrice());
			result.setAskQuantity(ask.getQuantity());
		}
		Order bid = bids.first();
		if (bid != null) {
			result.setBidPrice(bid.getPrice());
			result.setBidPrice(bid.getQuantity());
		}
		return result;
	}

	public List<Order> getAsks() {
		return new ArrayList<Order>(asks);
	}

	public List<Order> getBids() {
		return new ArrayList<Order>(bids);
	}
	
	public boolean remove(Order order) {
		if (order.isBid()) {
			return bids.remove(order);
		} else {
			return asks.remove(order);
		}
	}
	
	public boolean contains(Order order) {
		if (order.isAsk()) {
			return asks.contains(order);
		} else {
			return bids.contains(order);
		}
	}
	
	public List<Order> getAllOrders() {
		ArrayList<Order> result = 
			new ArrayList<Order>(bids.size() + asks.size());
		result.addAll(bids);
		result.addAll(asks);
		return result;
	}
	
	public boolean isEmpty() {
		return asks.isEmpty() && bids.isEmpty();
	}
	
	/**
	 * Add a new order to the book.
	 * 
	 * @param order  The new order to add
	 * @return true if the order was successfully added, false
	 *          if the order book is full. 
	 */
	public boolean add(Order order, MarketState marketState) {
		boolean result = false;
		if (order.isBid()) {
			result = bids.add(order);
		} else  {
			result = asks.add(order);
		} 
		return result;
	}

	public String toString() {
		return "(" + getClass() + " asks:" + asks + " bids:" + bids + ")";
	}
}
